import torch

'''
数据类型 dtype  
a = torch.FloatTensor(32)
type(a)
<class 'torch.Tensor'>
a.type()
'torch.FloatTensor'
b = torch.DoubleTensor(32)
b.type()
'torch.DoubleTensor'
c = torch.HalfTensor(32)
c.type()
'torch.HalfTensor'
d = torch.ByteTensor(32)
d.type()
'torch.ByteTensor'
e = torch.CharTensor(32)

'''


'''
创建张量
a = torch.tensor([2,3,4])

numpy --> tensor
转换后的tensor与numpy指向同一地址，所以对其中一个变量的值改变另一方也会随之改变
a = np.array([2,3,4])
b = torch.from_numpy(a)
如果想把CUDA tensor格式的数据改成numpy时，需要先将其转换成cpu float-tensor随后再转到numpy格式。
numpy不能直接读取CUDA tensor，需要将它转化为 CPU tensor。 
tensor --> numpy
c = b.numpy()

torch.Tensor和torch.from.numpy都可以将numpy类转化为tensor类，但torch.from.numpy更加安全，使用torch.Tensor在非float类型下会与预期不符。
也就是说，当转换的源是float类型，torch.Tensor与torch.from.numpy会共享一块内存，且转换后的结果类型都是torch.float32。
当转换的源不是float类型，torch.Tensor得到的是torch.float32，而torch.from_numpy则是与源类型一致。


'''

'''
s = torch.arange(0,10,2)
print(s)

s1 = torch.linspace(0,10,4)


s2 = torch.empty(3,4)
print(a)
简单说明，这个空里面还是有值的。一旦您调用 torch.empty() ，根据张量的大小(形状)分配一 block 内存。未初始化的数据意味着 torch.empty() 
将简单地按原样返回内存块中的值。这些值可能是默认值，也可能是由于某些其他操作而存储在这些内存块中的值，这些操作之前使用了内存块的那部分。
'''


'''
m1 = torch.Tensor(2,3)
m2 = torch.tensor([2,3])
（1）torch.tensor是从数据中推断数据类型，而torch.Tensor是torch.empty(会随机产生垃圾数组)和torch.tensor之间的一种混合。但是，
当传入数据时，torch.Tensor使用全局默认dtype(FloatTensor)；

（2）torch.tensor(1)返回一个固定值1，而torch.Tensor(1)返回一个大小为1的张量，它是初始化的随机值。
'''

'''
a = torch.rand(3,3)
b = torch.rand_like(a)
c = torch.randint(1,10,(3,3))
a
tensor([[0.8497, 0.4820, 0.9545],
        [0.6037, 0.0167, 0.2913],
        [0.9597, 0.1733, 0.6014]])
b
tensor([[0.6124, 0.7888, 0.0258],
        [0.7556, 0.9890, 0.9809],
        [0.0556, 0.9611, 0.2539]])
c
tensor([[9, 9, 7],
        [8, 3, 3],
        [9, 2, 8]])

'''

'''
a = torch.linspace(1,12,steps=12)
a = a.view(3,4)
b = torch.index_select(a,0,torch.tensor([0,2]))
c = torch.index_select(a,1,torch.tensor([1,3]))


a
tensor([[ 1.,  2.,  3.,  4.],
        [ 5.,  6.,  7.,  8.],
        [ 9., 10., 11., 12.]])
b
tensor([[ 1.,  2.,  3.,  4.],
        [ 9., 10., 11., 12.]])
c
tensor([[ 2.,  4.],
        [ 6.,  8.],
        [10., 12.]])
        
        
view函数和reshape函数在我们使用过程中的基本功能是类似的，reshape可在不连续的情况下不会报错
对于-1的用法，两者都是:如果输入(B, C, H, W)经过view(B, -1)或者reshape(B, -1)都会变成(B, W×H×C)，而不是(B, C×H×W)，这是需要特别注意的。【即反着来的】

'''


'''
expand()
这个函数的作用就是对指定的维度进行数值大小的改变。只能改变维大小为1的维，否则就会报错。
不改变的维可以传入-1或者原来的数值。
torch.Tensor.expand(*sizes) → Tensor


a=torch.randn(1,1,3,768)
print(a) 
print(a.shape) #torch.Size([1, 1, 3, 768])
b=a.expand(2,-1,-1,-1)
print(b)
print(b.shape) #torch.Size([2, 1, 3, 768])
c=a.expand(2,1,3,768)
print(c.shape) #torch.Size([2, 1, 3, 768])


repeat(*sizes)

沿着指定的维度，对原来的tensor进行数据复制。这个函数和expand()还是有点区别的。
expand()只能对维度为1的维进行扩大，而repeat()对所有的维度可以随意操作。

a=torch.randn(2,1,768)
print(a)
print(a.shape) #torch.Size([2, 1, 768])
b=a.repeat(1,2,1)
print(b)
print(b.shape) #torch.Size([2, 2, 768])
c=a.repeat(3,3,3)
print(c)
print(c.shape) #torch.Size([6, 3, 2304])


broadcast    能够进行维度的扩展，相当于expand，但是是自动扩展。扩展的时候不需要拷贝数据
主要思想：依次从最后一个维度开始匹配，若前面没有维度则插入一个新的维度，size =1，且自动调用expand函数使得维度size相同
'''


'''
cat(seq,dim,out=None)，表示把两个或者多个tensor拼接起来。
其中 seq表示要连接的两个序列，以元组的形式给出，例如:seq=(a,b), a,b 为两个可以连接的序列
dim 表示以哪个维度连接，dim=0, 横向连接   dim=1,纵向连接

a=torch.randn(4,3)
b=torch.randn(4,3)
 
c=torch.cat((a,b),dim=0)#横向拼接，增加行 torch.Size([8, 3])
print(c.shape)
d=torch.cat((a,b),dim=1)#纵向拼接，增加列 torch.Size([4, 6])
print(d.shape)

x = torch.rand((2,2,3))
y = torch.rand((2,2,3))
print("x:",x)
print("y:",y)
print("dim=0:", torch.stack((x,y),dim=0))
print("dim=1:", torch.stack((x,y), dim=1))
print("dim=2:", torch.stack((x, y), dim=2))
print("dim=3", torch.stack((x, y), dim=3))


stack操作后会在原来的基础上再增加一维，比如原来两个tensor的维度都是3维，经过stack后的结果为4维tensor；
而cat操作其结果和原来的tensor保持一致,
'''

'''
a = torch.rand(5,32,8)
b = torch.split(a,2,0)
print(a.shape)
print(len(b))
print(b[0].shape)  #b是三个元组
print(b[1].shape)
print(b[2].shape)

torch.Size([5, 32, 8])
3
torch.Size([2, 32, 8])
torch.Size([2, 32, 8])
torch.Size([1, 32, 8])




a = torch.rand(5,32,8)
b = torch.chunk(a,3,0)
print(b[0].shape)  #b是三个元组
print(b[1].shape)
print(b[2].shape)

torch.Size([2, 32, 8])
torch.Size([2, 32, 8])
torch.Size([1, 32, 8])
'''

'''
上限与下限
a = torch.rand(3,3)*20
b = a.clamp(0,10)
c = a.clamp(7,14)
'''